package com.polaris.live.utils.zego

import android.os.Looper
import android.view.TextureView
import com.polaris.live.common.util.LogExt
import com.polaris.live.utils.zego.LivePlayer.startLive
import com.polaris.live.utils.zego.LivePlayer.stopLive
import com.polaris.live.utils.zego.listener.OnLivePlayListener
import im.zego.zegoexpress.callback.IZegoEventHandler
import im.zego.zegoexpress.constants.ZegoPlayerState
import im.zego.zegoexpress.constants.ZegoRemoteDeviceState
import im.zego.zegoexpress.constants.ZegoStreamResourceMode
import im.zego.zegoexpress.constants.ZegoViewMode
import im.zego.zegoexpress.entity.ZegoCanvas
import im.zego.zegoexpress.entity.ZegoPlayStreamQuality
import im.zego.zegoexpress.entity.ZegoPlayerConfig
import org.json.JSONObject
import java.lang.ref.WeakReference

/**
 * 直播流播放器，列表中需要自行管理
 *
 * 如果调用了[startLive]，必须调用[stopLive]，否则会发生内存泄漏
 *
 * @author Created by lucas on 2023/10/17 19:27
 * @since 1.0.0
 */
object LivePlayer {

    private const val TAG = "LivePlayer"
    private val eventHandler = object : IZegoEventHandler() {
        override fun onPlayerStateUpdate(
            streamID: String?,
            state: ZegoPlayerState?,
            errorCode: Int,
            extendedData: JSONObject?
        ) {
            super.onPlayerStateUpdate(streamID, state, errorCode, extendedData)
            LogExt.logI(TAG, "onPlayerStateUpdate  streamID：$streamID  $state   $errorCode ")
            if (streamID != null && streamID == lastStreamId) {
                if (errorCode != 0) {
                    oneRenderVideoFirstFrame = false
                }
                playerErrorCode = errorCode
                onLivePlayListener?.onPlayerStateUpdate(state, errorCode, extendedData)
            }
        }

        override fun onPlayerRenderVideoFirstFrame(streamID: String?) {
            LogExt.logI(TAG, "onPlayerRenderVideoFirstFrame  streamID：$streamID ")
            if (streamID != null && streamID == lastStreamId) {
                oneRenderVideoFirstFrame = true
                onLivePlayListener?.onPlayerRenderVideoFirstFrame()
            }
        }

        override fun onRemoteSpeakerStateUpdate(streamID: String?, state: ZegoRemoteDeviceState?) {
            LogExt.logI(TAG, "onRemoteSpeakerStateUpdate  streamID：$streamID    $state")
            if (streamID != null && streamID == lastStreamId && state != null) {
                if (state != ZegoRemoteDeviceState.OPEN) {
                    oneRenderVideoFirstFrame = false
                }
                zegoRemoteDeviceState = state
                onLivePlayListener?.onRemoteSpeakerStateUpdate(state)
            }
        }

        /**
         *level 代表了拉流质量的综合分数，大部分情况下，开发者可以参考此分数展示下行网络的质量
         * "mos" 字段，表示对拉流音质的评分。开发者对音频质量比较关注时
         */
        override fun onPlayerQualityUpdate(streamID: String?, quality: ZegoPlayStreamQuality?) {
            LogExt.logI(
                TAG,
                "onPlayerQualityUpdate  streamID：$streamID    ${quality?.videoDecodeFPS}  ${quality?.audioDecodeFPS}"
            )
            if (streamID != null && streamID == lastStreamId && quality != null) {
                if (!oneRenderVideoFirstFrame && quality.videoRenderFPS != 0.0) {
                    oneRenderVideoFirstFrame = true
                    onLivePlayListener?.onPlayerRenderVideoFirstFrame()
                }
                onLivePlayListener?.onPlayerQualityUpdate(quality)
            }
        }
    }

    /**
     * 在播放的流是否相等
     */
    fun playingStreamId(streamId: String?): Boolean {
        return streamId == lastStreamId
    }

    /**
     * 流是否在播放
     */
    fun isStreamIdPaly(streamId: String): Boolean {
        return if (streamId == lastStreamId) {
            !(playerErrorCode != 0 || !oneRenderVideoFirstFrame || zegoRemoteDeviceState == null || zegoRemoteDeviceState != ZegoRemoteDeviceState.OPEN)
        } else {
            false
        }
    }

    init {
        LiveEngineManage.eventHandlerHelper.addEventHandler(eventHandler)
    }

    private var lastFace: LiveActivityIdentifier = LiveActivityIdentifier.NO_FCE

    private var viewKey: WeakReference<TextureView>? = null

    /**
     * S上次播放的流Id
     */
    private var lastStreamId: String? = null
    private var onLivePlayListener: OnLivePlayListener? = null

    /**
     * 处理错误，以便如果是相同流没有启动状态监听
     */
    private var zegoRemoteDeviceState: ZegoRemoteDeviceState? = null
    private var oneRenderVideoFirstFrame: Boolean = false
    private var playerErrorCode: Int = 0

    fun startLive(
        streamId: String,
        view: TextureView,
        face: LiveActivityIdentifier,
        isMute: Boolean,
        onLivePlayListener2: OnLivePlayListener?,
        playMode: ZegoStreamResourceMode = ZegoStreamResourceMode.ONLY_L3,
    ) {
        LogExt.logI(TAG, "startLive  streamID：$streamId    face:$face isMute$isMute")
        check(Looper.myLooper() == Looper.getMainLooper()) {
            "The stream must be played on the main thread."
        }

        var isCallbackStart = true  //设置上次是否在正常工作
        if (streamId != lastStreamId) {
            stopLive()
        } else {
            /**
             * 正常播放
             */
            val shouldStartPlayback =
                playerErrorCode == 0 && oneRenderVideoFirstFrame && zegoRemoteDeviceState == ZegoRemoteDeviceState.OPEN
            if (shouldStartPlayback) {
                // 如果满足播放条件，则执行以下操作：
                isCallbackStart = false
                onLivePlayListener?.onPlayStart()
            }

            if (playerErrorCode != 0) {
                onLivePlayListener2?.onPlayerStateUpdate(null, playerErrorCode, null)
            }
            zegoRemoteDeviceState?.apply {
                onLivePlayListener2?.onRemoteSpeakerStateUpdate(this)
            }
            if (oneRenderVideoFirstFrame) {
                onLivePlayListener2?.onPlayerRenderVideoFirstFrame()
            }

        }

        onLivePlayListener = onLivePlayListener2
        lastFace = face
        viewKey = WeakReference(view)
        lastStreamId = streamId

        val playCanvas = ZegoCanvas(view).apply {
            viewMode = ZegoViewMode.ASPECT_FILL
        }
        LiveEngineManage.getEngine()?.mutePlayStreamAudio(streamId, isMute)
        val playerConfig = ZegoPlayerConfig().apply { resourceMode = playMode }
        LiveEngineManage.getEngine()?.startPlayingStream(streamId, playCanvas, playerConfig)
        if (isCallbackStart) {
            onLivePlayListener?.onPlayStart()
        }
    }

    fun stopLive(face: LiveActivityIdentifier) {
        if (lastFace == face) {
            LogExt.logI(TAG, "stopLive  lastStreamId：$lastStreamId    face:$face ")
            stopLive()
        }
    }

    fun stopLive(view: TextureView) {
        if (viewKey?.get() == view) {
            LogExt.logI(TAG, "stopLive  lastStreamId：$lastStreamId    view:$view ")
            stopLive()
        }
    }

    fun stopLive(streamId: String) {
        if (streamId == lastStreamId) {
            LogExt.logI(TAG, "stopLive  lastStreamId：$lastStreamId    streamId:$streamId ")
            stopLive()
        }
    }

    private fun stopLive() {
        check(Looper.myLooper() == Looper.getMainLooper()) {
            "The stream must be played on the main thread."
        }
        LogExt.logI(TAG, "stopLive  lastStreamId：$lastStreamId  ------kill-----")
        lastStreamId?.let {
            onLivePlayListener?.onPlayStop()
            LiveEngineManage.getEngine()?.stopPlayingStream(it)
        }
        onLivePlayListener = null
        lastFace = LiveActivityIdentifier.NO_FCE
        zegoRemoteDeviceState = null
        lastStreamId = null
        oneRenderVideoFirstFrame = false
        playerErrorCode = 0
        viewKey = null

    }
}
